#include "fyp/render/RenderedTextureImpl.h"

//------------------------------------------------------------------------------
// additional header includes
#include <d3d9.h>

#include "fyp/render/ResourceFactory.h"

//------------------------------------------------------------------------------
namespace ming
{
namespace fyp
{
namespace render
{
	//--------------------------------------------------------------------------
	TRenderedTextureImpl::TRenderedTextureImpl(
		FORMAT format,
		size_t w,
		size_t h,
		bool hasDepth,
		TResourceFactory *resFactory) :
		mResFactory(resFactory)
	{
		mTexture		= NULL;
		mRenderTarget	= NULL;
		mDepthBuf		= NULL;

		get<0>(mLogicalSize) = w;
		get<1>(mLogicalSize) = h;

		FindMatchingPow2Size(w, h);

		mTexture = mResFactory->LoadRenderedTexture(format, w, h);

		if(mTexture)
		{
			mTexture->GetSurfaceLevel(0, &mRenderTarget);

			if(hasDepth)
				mDepthBuf = mResFactory->LoadDepthBuffer(w, h);
		}
	}
	
	//--------------------------------------------------------------------------
	TRenderedTextureImpl::~TRenderedTextureImpl()
	{
		if(mRenderTarget)
			mRenderTarget->Release();
		
		mResFactory->UnloadRenderedTexture(mTexture);
		mResFactory->UnloadDepthBuffer(mDepthBuf);
	}

	//--------------------------------------------------------------------------
	void* TRenderedTextureImpl::GetApiTexture()
	{
		return mTexture;
	}

	//--------------------------------------------------------------------------
	void* TRenderedTextureImpl::GetApiRenderTarget()
	{
		return mRenderTarget;
	}

	//--------------------------------------------------------------------------
	void* TRenderedTextureImpl::GetApiDepthBuffer()
	{
		return mDepthBuf;
	}

	//--------------------------------------------------------------------------
	tuple<size_t, size_t> TRenderedTextureImpl::GetLogicalSize()
	{
		return mLogicalSize;
	}

	//--------------------------------------------------------------------------
	tuple<size_t, size_t> TRenderedTextureImpl::GetActualSize()
	{
		if(!mTexture)
			return core::make_tuple(size_t(0), size_t(0));

		D3DSURFACE_DESC desc;
		mTexture->GetLevelDesc(0, &desc);

		return core::make_tuple(size_t(desc.Width), size_t(desc.Height));
	}

	//--------------------------------------------------------------------------
	void TRenderedTextureImpl::SetAddressMode(
		TAddressMode u,
		TAddressMode v,
		TAddressMode w)
	{
		get<0>(mAddressModes) = u;
		get<1>(mAddressModes) = v;
		get<2>(mAddressModes) = w;
	}

	//--------------------------------------------------------------------------
	void TRenderedTextureImpl::SetFilterMode(
		TFilterMode minFilter,
		TFilterMode magFilter,
		TFilterMode mipFilter)
	{
		get<0>(mFilterModes) = minFilter;
		get<1>(mFilterModes) = magFilter;
		get<2>(mFilterModes) = mipFilter;
	}

	//--------------------------------------------------------------------------
	ITexture::TAddressModeSettings TRenderedTextureImpl::GetAddressMode()
	{
		return mAddressModes;
	}
	
	//--------------------------------------------------------------------------
	ITexture::TFilterModeSettings TRenderedTextureImpl::GetFilterMode()
	{
		return mFilterModes;
	}

	//--------------------------------------------------------------------------
	void TRenderedTextureImpl::FindMatchingPow2Size(
		size_t &w,
		size_t &h)
	{
		size_t pwd_2_size[] = {
			1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096};

		size_t outW, outH;
		size_t i;

		i=0;
		while(i<13 && w >= pwd_2_size[i])
			outW = pwd_2_size[i++];

		i=0;
		while(i<13 && h >= pwd_2_size[i])
			outH = pwd_2_size[i++];

		w = outW;
		h = outH;
	}
	
	//--------------------------------------------------------------------------
}
}
}
